/* 
 * File:   Particle.h
 * Author: RedEyedKiller
 *
 * Created on 14 Ιούλιος 2010, 1:26 πμ
 */

#ifndef PARTICLE_H
#define	PARTICLE_H

#include "PhysicalObject.h"

using namespace Math;

namespace physicsSystem
{

namespace particleSystem
{

/**
 * The fundamental concept of particles system. This describes a physical object of
 * properties as position, mass and velociity but with no dimensions.
 *
 * When updated it calculates its velocity and position.
 */
class Particle : public physicsSystem::PhysicalObject
{
public:

    Particle():scale(1,1),color(gl::colors::WHITE)
    {
        invertedMass = 1;
    }

    Particle(float posX, float posY, float velX, float velY, float mass)
    : PhysicalObject(velX,velY,0.0f,0.0f),position(posX,posY),scale(1,1),color(gl::colors::WHITE)
    {
        if(mass == 0)
            invertedMass = 0;
        else
            this->invertedMass = 1/mass;
        currentLife = 0;
        damping = 1;
    }

    virtual void Update(float seconds)
    {
        //calculate new position
        position += velocity*seconds;
        //calculate moment's acceleration
        Math::Vector2F acceleration(generalAcceleration);
        //by adding general acceleration with Σf/mass
        acceleration += forces * invertedMass;
        //ccalculate new velocity
        velocity += acceleration*seconds;
        //velocity *= damping * seconds;
        currentLife += seconds;
        ResetForces();
    }
    
    void UpdateScale(const Vector2F& start,const Vector2F& end,float lifetime)
    {
        scale = Math::CosineInterpolation(start + start * scaleVariation,end + end * scaleVariation,currentLife/lifetime);
    }
    
    void UpdateColor(const gl::Color& birth,const gl::Color& death,float lifetime)
    {
        color = Math::CosineInterpolation(birth,death,currentLife/lifetime);
    }

    inline void SetPosition(const Vector2F& position)
    {
        this->position = position;
    }

    void Move(float x, float y)
    {
        position.Move(x, y);
    }

    inline void SetPosition(float x, float y)
    {
        position.Set(x, y);
    }

    virtual inline Vector2F GetPosition() const
    {
        return position;
    }

    inline void SetCurrentLife(unsigned long int currentLife)
    {
        this->currentLife = currentLife;
    }

    inline unsigned long int GetCurrentLife() const
    {
        return currentLife;
    }

    inline bool IsAlive(unsigned long int lifetime)
    {
        return currentLife < lifetime;
    }

    void SetColor(const gl::Color& color)
    {
        this->color = color;
    }

    gl::Color GetColor() const
    {
        return color;
    }

    const Vector2F GetScale() const
    {
        return scale;
    }

    void SetScale(const Vector2F& scale)
    {
        this->scale = scale;
    }

    void SetAngle(float angle)
    {
        this->angle = angle;
    }

    float GetAngle() const
    {
        return angle;
    }

    void SetScaleVariation(float scaleVariation)
    {
        this->scaleVariation = scaleVariation;
        scale += scale * scaleVariation;
    }

private:
    Vector2F position;
    Vector2F scale;
    float scaleVariation;
    gl::Color color;
    float currentLife;
    float angle;
};

};
};
#endif	/* PARTICLE_H */
